﻿using OxyPlot;
using OxyPlot.Annotations;
using OxyPlot.Wpf;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;

namespace OxyPlotTester
{
    public static class OxyPlotExtension
    {
        /// <summary>
        /// [dlgcy] 只更新注解，避免卡顿（注意：1、需修改注解特征来匹配。2、支持版本为 2.1.0-Preview1。）
        /// </summary>
        /// <param name="plotModel"></param>
        public static void UpdateAnnotations(this PlotModel plotModel)
        {
            PlotView plotView = plotModel.PlotView as PlotView;
            if (plotView == null) return;

            BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance;
            Type type = plotView.GetType();
            PropertyInfo propertyInfo = type.GetProperty("RenderContext", flags);
            var renderContext = propertyInfo?.GetValue(plotView) as CanvasRenderContext;
            if (renderContext == null) return;

            lock (plotModel.SyncRoot)
            {
                var initialClipCount = renderContext.ClipCount;

                #region 去除拖动产生的残留影像

                propertyInfo = type.GetProperty("Canvas", flags);
                var canvas = propertyInfo?.GetValue(plotView) as Canvas;
                List<UIElement> elements = new List<UIElement>();
                foreach (UIElement canvasChild in canvas.Children)
                {
                    //此处取反的括号内填写需要去除的注解的特征;
                    if (!(canvasChild is Image || canvasChild is Path { StrokeThickness: 5 }))
                    {
                        elements.Add(canvasChild);
                    }
                }

                canvas.Children.Clear();
                elements.ForEach(x => canvas.Children.Add(x));

                #endregion

                try
                {
                    Type type2 = plotModel.GetType();
                    MethodInfo methodInfo = type2.GetMethod("RenderAnnotations", flags);
                    methodInfo?.Invoke(plotModel, new object[] { renderContext, AnnotationLayer.AboveSeries });

                    if (renderContext.ClipCount != initialClipCount + 1)
                    {
                        throw new InvalidOperationException("Unbalanced calls to IRenderContext.PushClip were made during rendering.");
                    }
                }
                catch (Exception ex)
                {
                    while (renderContext.ClipCount > initialClipCount)
                    {
                        renderContext.PopClip();
                    }
                }
                finally
                {
                    // Clean up unused images
                    renderContext.CleanUp();
                }
            }
        }
    }
}
